/**
 * Notes: 管理员管理
 * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY cclinux0730 (wechat)
 * Date: 2021-07-11 07:48:00 
 */

const BaseProjectAdminService = require('./base_project_admin_service.js');
const util = require('../../../../framework/helpers/util.js');
const dataUtil = require('../../../../framework/helpers/data_util.js');
const timeUtil = require('../../../../framework/helpers/time_util.js');
const AdminModel = require('../../../../config/models_config').admin_model;
const LogModel = require('../../../../config/models_config').log_model;
const { md5Lib } = require('../../../../framework/lib_config.js');
const LogCache = require('../../../../framework/platform/cache/log_cache.js');

class AdminMgrService extends BaseProjectAdminService {

	//**管理员登录  */
	async adminLogin(name, password, openId) {
		console.log(`[adminLogin] 尝试登录: ${name}`);

		try {
			// 判断是否存在
			let where = {
				ADMIN_STATUS: 1,
				ADMIN_NAME: name,
				ADMIN_PASSWORD: md5Lib.md5(password)
			}
			console.log(`[adminLogin] 查询条件:`, where);

			// 直接检查管理员模型是否可用
			if (!AdminModel) {
				console.error('[adminLogin] AdminModel未定义');
				this.AppError('系统配置错误，请联系管理员');
			}

			// 尝试获取管理员信息
			let fields = 'ADMIN_ID,ADMIN_NAME,ADMIN_DESC,ADMIN_TYPE,ADMIN_LOGIN_TIME,ADMIN_LOGIN_CNT';
			
			console.log('[adminLogin] 执行查询...');
			let admin = null;
			
			try {
				admin = await AdminModel.getOne(where, fields);
				console.log('[adminLogin] 查询结果:', admin ? '成功' : '失败');
			} catch (queryErr) {
				console.error('[adminLogin] 查询管理员记录失败:', queryErr);
				
				// 尝试直接通过数据库API查询
				try {
					console.log('[adminLogin] 尝试使用数据库API直接查询');
					const cloudBase = require('../../../../framework/cloud/cloud_base.js');
					const db = cloudBase.getCloud().database();
					const adminColl = db.collection('oa_admin');
					
					const result = await adminColl.where(where).get();
					if (result && result.data && result.data.length > 0) {
						admin = result.data[0];
						console.log('[adminLogin] 直接查询成功');
					} else {
						console.log('[adminLogin] 直接查询未找到记录');
					}
				} catch (directQueryErr) {
					console.error('[adminLogin] 直接查询也失败:', directQueryErr);
				}
			}
			
			// 如果管理员不存在，提示用户
			if (!admin) {
				console.log('[adminLogin] 管理员不存在或密码错误');
				this.AppError('管理员不存在或者已停用');
			}

			let cnt = admin.ADMIN_LOGIN_CNT || 0;

			// 生成token
			let token = dataUtil.genRandomString(32);
			let tokenTime = timeUtil.time();
			let data = {
				ADMIN_TOKEN: token,
				ADMIN_TOKEN_TIME: tokenTime,
				ADMIN_LOGIN_TIME: timeUtil.time(),
				ADMIN_LOGIN_CNT: cnt + 1
			}
			
			// 更新管理员登录信息
			try {
				await AdminModel.edit(where, data);
				console.log('[adminLogin] 更新管理员登录信息成功');
			} catch (updateErr) {
				console.error('[adminLogin] 更新管理员登录信息失败:', updateErr);
				
				// 尝试直接更新
				try {
					console.log('[adminLogin] 尝试直接更新登录信息');
					const cloudBase = require('../../../../framework/cloud/cloud_base.js');
					const db = cloudBase.getCloud().database();
					
					await db.collection('oa_admin').where(where).update({
						data
					});
					
					console.log('[adminLogin] 直接更新成功');
				} catch (directUpdateErr) {
					console.error('[adminLogin] 直接更新失败:', directUpdateErr);
					// 继续处理，允许登录但不更新信息
				}
			}

			let type = admin.ADMIN_TYPE || 0;
			let last = (!admin.ADMIN_LOGIN_TIME) ? '尚未登录' : timeUtil.timestamp2Time(admin.ADMIN_LOGIN_TIME);

			// 写日志
			try {
				this.insertLog('登录了系统', admin, LogModel.TYPE.SYS);
				console.log('[adminLogin] 写入登录日志成功');
			} catch (logErr) {
				console.error('[adminLogin] 写入登录日志失败:', logErr);
			}

			console.log('[adminLogin] 登录成功');
			return {
				token,
				name: admin.ADMIN_NAME,
				type,
				last,
				cnt
			}
		} catch (err) {
			console.error('[adminLogin] 登录过程中发生错误:', err);
			throw err;
		}
	}

	async clearLog() {
		// 获取项目ID
		const projectId = this.getProjectId();
		
		// 完全清空所有日志
		try {
			// 删除全部日志
			let whereAll = {
				_pid: projectId
			};
			await LogModel.del(whereAll, true);
			
			// 添加一条清空日志的记录
			this.insertLog('已清空全部日志记录', this._admin, LogModel.TYPE.SYS, LogModel.LEVEL.INFO);
			
			// 清理日志缓存
			await LogCache.cleanExpiredLogs();
			
			return { success: true };
		} catch (error) {
			console.error('日志清理失败:', error);
			// 记录失败日志
			this.insertLog('日志清理失败: ' + error.message, this._admin, LogModel.TYPE.SYS, LogModel.LEVEL.ERROR);
			return { success: false, error: error.message };
		}
	}

	/** 取得日志分页列表 */
	async getLogList({
		search, // 搜索条件
		sortType, // 搜索菜单
		sortVal, // 搜索菜单
		orderBy, // 排序
		whereEx, //附加查询条件 
		page,
		size,
		oldTotal = 0,
		ignoreCache = false // 是否忽略缓存
	}) {

		// 缓存KEY
		const cacheKey = `log_list_${this.getProjectId()}_${page}_${size}_${search}_${sortType}_${sortVal}`;
		const cacheTime = 60 * 5; // 缓存5分钟
		
		// 尝试从缓存获取
		let result = null;
		if (!ignoreCache) {
			result = await this.getCache(cacheKey);
			if (result) {
				return result;
			}
		}

		orderBy = orderBy || {
			LOG_ADD_TIME: 'desc'
		};
		
		// 仅查询需要的字段，提高查询性能
		let fields = 'LOG_ID,LOG_ADMIN_NAME,LOG_ADMIN_DESC,LOG_CONTENT,LOG_TYPE,LOG_ADD_TIME,LOG_LEVEL';
		
		let where = {};

		if (util.isDefined(search) && search) {
			where.or = [{
				LOG_CONTENT: ['like', search]
			}, {
				LOG_ADMIN_DESC: ['like', search]
			}, {
				LOG_ADMIN_NAME: ['like', search]
			}];

		} else if (sortType && util.isDefined(sortVal)) {
			// 搜索菜单
			switch (sortType) {
				case 'type':
					// 按类型
					where.LOG_TYPE = Number(sortVal);
					break;
				case 'level':
					// 按级别
					where.LOG_LEVEL = Number(sortVal);
					break;
			}
		}
		
		// 添加项目ID过滤
		where._pid = this.getProjectId();
		
		// 创建索引提高查询性能
		try {
			// 使用实例方法而非静态方法调用
			await LogModel.createIndex({
				LOG_ADD_TIME: -1,
				LOG_TYPE: 1,
				LOG_LEVEL: 1
			});
		} catch (error) {
			console.error('索引创建失败', error);
			// 失败时不阻断主流程
		}
		
		result = await LogModel.getList(where, fields, orderBy, page, size, true, oldTotal);

		// 设置缓存
		await this.setCache(cacheKey, result, cacheTime);

		return result;
	}

	/** 获取所有管理员 */
	async getMgrList({
		search, // 搜索条件
		sortType, // 搜索菜单
		sortVal, // 搜索菜单
		orderBy, // 排序
		whereEx, //附加查询条件
		page,
		size,
		isTotal = true,
		oldTotal
	}) {
		orderBy = {
			ADMIN_ADD_TIME: 'desc'
		}
		let fields = 'ADMIN_NAME,ADMIN_STATUS,ADMIN_PHONE,ADMIN_TYPE,ADMIN_LOGIN_CNT,ADMIN_LOGIN_TIME,ADMIN_DESC,ADMIN_EDIT_TIME,ADMIN_EDIT_IP';

		let where = {};
		where.and = {
			_pid: this.getProjectId() //复杂的查询在此处标注PID
		};
		if (util.isDefined(search) && search) {
			where.or = [{
				ADMIN_NAME: ['like', search]
			},
			{
				ADMIN_PHONE: ['like', search]
			},
			{
				ADMIN_DESC: ['like', search]
			}
			];
		} else if (sortType && util.isDefined(sortVal)) {
			// 搜索菜单
			switch (sortType) {
				case 'status':
					// 按类型
					where.and.ADMIN_STATUS = Number(sortVal);
					break;
				case 'type':
					// 按类型
					where.and.ADMIN_TYPE = Number(sortVal);
					break;
			}
		}

		return await AdminModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal);
	}

	/** 删除管理员 */
	async delMgr(id, myAdminId) {
		// 判断管理员是否存在
		let where = {
			_id: id
		}
		let admin = await AdminModel.getOne(where);
		if (!admin)
			this.AppError('管理员不存在');

		// 不能删除自己
		if (id === myAdminId)
			this.AppError('不能删除自己');

		// 不能删除超级管理员
		if (admin.ADMIN_TYPE == 1)
			this.AppError('超级管理员不可删除');

		await AdminModel.del(where);

		// 写入日志
		this.insertLog('删除了管理员「' + admin.ADMIN_NAME + '」', this._admin, LogModel.TYPE.SYS);
	}

	/** 添加新的管理员 */
	async insertMgr(adminData) {
		// 判断是否已存在
		let where = {
			ADMIN_NAME: adminData.name
		}
		let cnt = await AdminModel.count(where);
		if (cnt > 0)
			this.AppError('该账号已经存在');

		// 生成新的管理员记录
		let data = {
			ADMIN_NAME: adminData.name,
			ADMIN_DESC: adminData.desc,
			ADMIN_PHONE: adminData.phone,
			ADMIN_PASSWORD: md5Lib.md5(adminData.password),
			ADMIN_TYPE: 0, // 默认普通管理员
			ADMIN_STATUS: 1, // 默认启用
			ADMIN_LOGIN_CNT: 0,
			ADMIN_LOGIN_TIME: 0,
			ADMIN_TOKEN: '',
			ADMIN_TOKEN_TIME: 0,
			ADMIN_ADD_TIME: timeUtil.time(),
			ADMIN_EDIT_TIME: timeUtil.time(),
			ADMIN_ADD_IP: this._ip,
			ADMIN_EDIT_IP: this._ip
		}

		let id = await AdminModel.insert(data);

		// 写入日志
		this.insertLog('添加了新管理员「' + data.ADMIN_NAME + '」', this._admin, LogModel.TYPE.SYS);

		return id;
	}

	/** 修改状态 */
	async statusMgr(id, status) {
		// 判断管理员是否存在
		let where = {
			_id: id
		}
		let admin = await AdminModel.getOne(where);
		if (!admin)
			this.AppError('管理员不存在');

		// 不能修改超级管理员状态
		if (admin.ADMIN_TYPE == 1)
			this.AppError('超级管理员不可停用');

		// 修改状态
		let data = {
			ADMIN_STATUS: status,
			ADMIN_EDIT_TIME: timeUtil.time(),
			ADMIN_EDIT_IP: this._ip
		}
		await AdminModel.edit(where, data);

		// 写入日志
		let statusDesc = status == 0 ? '停用' : '启用';
		this.insertLog(statusDesc + '了管理员「' + admin.ADMIN_NAME + '」', this._admin, LogModel.TYPE.SYS);
	}

	/** 获取管理员信息 */
	async getMgrDetail(id) {
		let fields = '*';

		let where = {
			_id: id
		}
		let mgr = await AdminModel.getOne(where, fields);
		if (!mgr) return null;

		return mgr;
	}

	/** 修改管理员 */
	async editMgr(id, adminData) {
		// 判断管理员是否存在
		let where = {
			_id: id
		}
		let admin = await AdminModel.getOne(where);
		if (!admin)
			this.AppError('管理员不存在');

		// 修改的数据
		let data = {
			ADMIN_NAME: adminData.name,
			ADMIN_DESC: adminData.desc,
			ADMIN_PHONE: adminData.phone,
			ADMIN_EDIT_TIME: timeUtil.time(),
			ADMIN_EDIT_IP: this._ip
		}

		// 如果有修改密码
		if (adminData.password) {
			data.ADMIN_PASSWORD = md5Lib.md5(adminData.password);
		}

		// 判断修改的账号是否已经存在
		if (admin.ADMIN_NAME != data.ADMIN_NAME) {
			let where = {
				ADMIN_NAME: data.ADMIN_NAME
			}
			let cnt = await AdminModel.count(where);
			if (cnt > 0)
				this.AppError('该账号已经存在');
		}

		await AdminModel.edit({
			_id: id
		}, data);

		// 写入日志
		this.insertLog('修改了管理员「' + admin.ADMIN_NAME + '」的信息', this._admin, LogModel.TYPE.SYS);
	}

	/** 修改自身密码 */
	async pwdtMgr(adminId, oldPassword, password) {
		// 判断管理员是否存在
		let where = {
			_id: adminId,
			ADMIN_PASSWORD: md5Lib.md5(oldPassword)
		}
		let admin = await AdminModel.getOne(where);
		if (!admin)
			this.AppError('旧密码错误');

		// 修改密码
		let data = {
			ADMIN_PASSWORD: md5Lib.md5(password),
			ADMIN_EDIT_TIME: timeUtil.time(),
			ADMIN_EDIT_IP: this._ip
		}
		await AdminModel.edit(where, data);

		// 写入日志
		this.insertLog('修改了自己的登录密码', admin, LogModel.TYPE.SYS);
	}

	/**
	 * 根据前缀清除缓存
	 * @param {string} prefix 缓存键前缀
	 */
	async clearCacheByPrefix(prefix) {
		try {
			// 如果存在缓存实例，使用其方法清除前缀缓存
			if (LogCache && typeof LogCache.clearCacheByPrefix === 'function') {
				await LogCache.clearCacheByPrefix(prefix);
				return true;
			}
			console.log('缓存系统不支持按前缀清除，尝试使用基础缓存操作');
			return false;
		} catch (error) {
			console.error('按前缀清除缓存失败:', error);
			return false;
		}
	}
}

module.exports = AdminMgrService;